#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <string>
#include <iostream>
#include <stdexcept>
#include <vector>
#include <thread>
#include <atomic>
#include <cstring>
#include "MessageFrame.h"

#define TYPE_EXPECTED 0xAA
#define MAX_MESSAGE_SIZE 512
#define MAX_PACKET_SIZE 60
#define MAX_PACKET_NUM ((MAX_MESSAGE_SIZE + (MAX_PACKET_SIZE - 1)) / MAX_PACKET_SIZE)

typedef struct
{
    uint8_t magic;
    uint8_t totalPackets;
    uint8_t currentPacketIndex;
    uint8_t packetLen;
    uint8_t data[0];
} Message;

typedef struct
{
    uint8_t magic;                  // T: 消息类型
    uint8_t totalPackets;           // L: 总包数
    uint8_t currentPacketIndex;     // 当前接收包的索引
    size_t receivedBytes;           // 已接收的字节数
    uint8_t data[MAX_MESSAGE_SIZE]; // 数据缓冲区
} MessageReceiver;
static MessageReceiver receiver;

void hexdump(const void *data, size_t size)
{
    const unsigned char *byte = (const unsigned char *)data;
    size_t i, j;

    for (i = 0; i < size; i += 16)
    {
        // 打印地址偏移
        printf("%08zx  ", i);

        // 打印十六进制数据
        for (j = 0; j < 16; j++)
        {
            if (i + j < size)
            {
                printf("%02x ", byte[i + j]);
            }
            else
            {
                printf("   "); // 填充空白
            }
        }

        // 分隔符
        printf(" ");

        // 打印ASCII字符
        for (j = 0; j < 16; j++)
        {
            if (i + j < size)
            {
                unsigned char ch = byte[i + j];
                printf("%c", isprint(ch) ? ch : '.');
            }
        }

        printf("\n");
    }
}

static void processPacket(MessageReceiver *receiver, const uint8_t *packet, size_t size)
{
    if (size < sizeof(Message))
    {
        return;
    }
    const Message *msg = (const Message *)packet;

    // 校验消息头的有效性
    if (msg->magic != TYPE_EXPECTED ||
        msg->totalPackets > MAX_PACKET_NUM ||
        msg->currentPacketIndex >= msg->totalPackets ||
        msg->packetLen > MAX_PACKET_SIZE)
    {
        return; // 无效消息头，直接返回
    }

    // 如果是第一个包，初始化接收器
    if (msg->currentPacketIndex == 0)
    {
        receiver->receivedBytes = 0;
        memset(receiver->data, 0, sizeof(receiver->data));
    }
    // 确保不会超出接收缓冲区
    if (receiver->receivedBytes + msg->packetLen >= sizeof(receiver->data))
    {
        return;
    }

    // 将当前包的数据复制到接收缓冲区
    memcpy(&receiver->data[receiver->receivedBytes], msg->data, msg->packetLen);
    receiver->receivedBytes += msg->packetLen;

    // 如果所有包接收完成，处理完整数据
    if (msg->totalPackets == msg->currentPacketIndex + 1)
    {
        printf("receiver->data: %s\n", receiver->data);
    }
}

class SerialPort
{
public:
    SerialPort(const std::string &devicePath, int baudRate)
        : fd(-1), devicePath(devicePath), baudRate(baudRate), running(false) {}

    ~SerialPort()
    {
        stopReceiving();
        closePort();
    }

    void openPort()
    {
        fd = open(devicePath.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
        if (fd < 0)
        {
            throw std::runtime_error("无法打开串口设备: " + std::string(strerror(errno)));
        }

        configurePort();
    }

    void closePort()
    {
        if (fd >= 0)
        {
            close(fd);
            fd = -1;
        }
    }

    void writeData(const std::vector<uint8_t> &packet)
    {
        ssize_t written = write(fd, packet.data(), packet.size());
        if (written < 0)
        {
            throw std::runtime_error("写入串口数据失败: " + std::string(strerror(errno)));
        }
    }

    void startReceiving()
    {
        if (running.load())
        {
            throw std::runtime_error("接收线程已在运行");
        }

        running.store(true);
        receiveThread = std::thread(&SerialPort::receiveLoop, this);
    }

    void stopReceiving()
    {
        running.store(false);
        if (receiveThread.joinable())
        {
            receiveThread.join();
        }
    }

private:
    int fd;
    std::string devicePath;
    int baudRate;
    std::atomic<bool> running;
    std::thread receiveThread;

    void configurePort()
    {
        struct termios tty
        {
        };
        if (tcgetattr(fd, &tty) != 0)
        {
            throw std::runtime_error("获取串口属性失败: " + std::string(strerror(errno)));
        }

        // 配置波特率
        speed_t speed;
        switch (baudRate)
        {
        case 115200:
            speed = B115200;
            break;
        case 9600:
            speed = B9600;
            break;
        default:
            throw std::invalid_argument("不支持的波特率");
        }

        cfsetospeed(&tty, speed);
        cfsetispeed(&tty, speed);

        // 配置控制模式
        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8位数据
        tty.c_cflag |= (CLOCAL | CREAD);            // 本地连接，启用接收器
        tty.c_cflag &= ~(PARENB | PARODD);          // 无校验
        tty.c_cflag &= ~CSTOPB;                     // 1个停止位
        tty.c_cflag &= ~CRTSCTS;                    // 禁用硬件流控制

        // 配置本地模式
        tty.c_lflag = 0; // 原始模式

        // 配置输入模式
        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // 禁用软件流控制

        // 配置输出模式
        tty.c_oflag = 0; // 原始模式

        // 配置超时
        tty.c_cc[VMIN] = 1;  // 至少读取一个字符
        tty.c_cc[VTIME] = 1; // 读取超时时间为 0.1 秒

        if (tcsetattr(fd, TCSANOW, &tty) != 0)
        {
            throw std::runtime_error("设置串口属性失败: " + std::string(strerror(errno)));
        }

        tcflush(fd, TCIOFLUSH); // 清空输入输出缓冲区
    }

    void receiveLoop()
    {
        const size_t bufferSize = 64;
        std::vector<char> buffer(bufferSize);

        while (running.load())
        {
            ssize_t bytesRead = read(fd, buffer.data(), buffer.size());
            if (bytesRead > 0)
            {
                std::string data(buffer.data(), bytesRead);
                processPacket(&receiver, reinterpret_cast<const uint8_t *>(buffer.data()), bytesRead);
            }
            else if (bytesRead < 0 && errno != EAGAIN)
            {
                std::cerr << "读取串口数据失败: " << strerror(errno) << std::endl;
                break;
            }
            usleep(10000); // 避免过多的 CPU 占用
        }
    }
};
struct Command
{
    std::string name;
    std::string json;
};
std::vector<Command> commands = {
    {"powerOff", "{\"Light\":{\"Power\":false}}"},
    {"powerON", "{\"Light\":{\"Power\":true}}"},
    {"addSchedule", "{\"Schedule\":{\"Schedules\":[{\"action\":{\"Switch\":{\"Power\":true}},\"id\":\"1VR1\",\"name\":\"test\",\"operation\":\"add\",\"triggers\":[{\"d\":0,\"m\":919}]}]}}"},
    {"removeSchedule", "{\"Schedule\":{\"Schedules\":[{\"id\":\"1VR1\",\"operation\":\"remove\"}]}}"},
    {"enableSchedule", "{\"Schedule\":{\"Schedules\":[{\"id\":\"1VR1\",\"operation\":\"enable\"}]}}"},
    {"disableSchedule", "{\"Schedule\":{\"Schedules\":[{\"id\":\"1VR1\",\"operation\":\"disable\"}]}}"}};
int main()
{
    try
    {
        SerialPort serial("/dev/ttyACM0", 115200);
        serial.openPort();

        // 启动接收线程
        serial.startReceiving();

        // 主线程用于发送数据
        std::string input;
        while (true)
        {
            std::cout << "input command、'exit'、'list': ";
            std::getline(std::cin, input);

            if (input == "exit")
            {
                break;
            }
            else if (input == "list")
            {
                for (const auto &cmd : commands)
                {
                    std::cout << cmd.name << std::endl;
                }
            }
            // 查找对应的 JSON 数据
            std::string jsonStr;
            bool found = false;
            for (const auto &cmd : commands)
            {
                if (cmd.name == input)
                {
                    jsonStr = cmd.json;
                    found = true;
                    break;
                }
            }
            MessageFrame message(jsonStr);
            // 逐包发送数据
            for (size_t i = 0; i < message.totalPackets(); ++i)
            {
                std::vector<uint8_t> packet = message.getPacket(i);
                serial.writeData(packet);
            }
        }

        serial.stopReceiving();
        serial.closePort();
    }
    catch (const std::exception &e)
    {
        std::cerr << "错误: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}